package org.linloong.modules.apis.monitor.sync;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import io.swagger.v3.oas.annotations.Hidden;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.linloong.modules.apis.monitor.entity.*;
import org.linloong.modules.apis.monitor.mapper.*;
import org.linloong.modules.apis.monitor.service.RealTimeDataService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Hidden // Swagger隐藏定时任务服务，不对外暴露（仅内部执行数据存储）
public class DailyDataSyncService {
    // 注入所有接口对应的MyBatis-Plus Mapper（与文档接口一一对应）
    private final WeatherDataMapper weatherDataMapper;
    private final PhenologyDataMapper phenologyDataMapper;
    private final CoverageDataMapper coverageDataMapper;
    private final CoveragePlusDataMapper coveragePlusDataMapper;
    private final SpectrumDataMapper spectrumDataMapper;
    private final PhenologyPlusDataMapper phenologyPlusDataMapper;
    private final InsectDataMapper insectDataMapper;
    private final AudioPatternDataMapper audioPatternDataMapper;
    private final RealTimeDataService realTimeDataService;
    private final WeatherDataParsedMapper weatherDataParsedMapper;
    private final DeviceInfoMapper deviceInfoMapper;
    private final SensorDataParser dataParser;
    private final DailyAggStatsMapper dailyAggStatsMapper;
    private final DeviceGroupMapper deviceGroupMapper;
    private final RedisTemplate<String, String> redisTemplate;
    private final static String START_DATE = "2022-01-01";
    private final static String STATISTICS_DATE_KEY = "sensor-statistics-date-%s";


    // 需同步数据的设备ID列表（可从数据库查询，示例为文档中常见设备ID格式）

    /**
     * 每日凌晨2点同步前一天数据（严格遵循文档"数据处理原则"第4点：用$filter限制时间范围，避免查询迟缓与数据量限制）
     * cron表达式：0 0 2 * * ? （秒 分 时 日 月 周，确保避开业务高峰期）
     */
//    @Scheduled(cron = "0 0 2 * * ?")
//    public void syncYesterdayData() {
//        // 1. 计算前一天时间范围（文档要求：时间使用Unix时间戳，ms计算）
//        LocalDate yesterday = LocalDate.now().minusDays(1);
//        // 开始时间：前一天00:00:00（Unix毫秒级时间戳）
//        Long startTimestamp = yesterday.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
//        // 结束时间：前一天23:59:59（Unix毫秒级时间戳）
//        Long endTimestamp = yesterday.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() - 1;
//        List<String> deviceIds = deviceInfoMapper.selectList(null).stream()
//                .map(DeviceInfo::getDeviceId)
//                .filter(Objects::nonNull)
//                .collect(Collectors.toList());
//        // 2. 遍历所有设备，同步文档中所有接口的前一天数据
//        deviceIds.forEach(deviceId -> {
//            syncWeatherData(deviceId, startTimestamp, endTimestamp);       // 同步气象数据（文档"气象数据接口"）
////            syncPhenologyData(deviceId, startTimestamp, endTimestamp);    // 同步物候数据（文档"物候接口"）
////            syncCoverageData(deviceId, startTimestamp, endTimestamp);     // 同步盖度数据（文档"盖度接口"）
////            syncCoveragePlusData(deviceId, startTimestamp, endTimestamp); // 同步盖度+数据（文档"盖度+接口"）
////            syncSpectrumData(deviceId, startTimestamp, endTimestamp);     // 同步光谱物候数据（文档"光谱物候接口"）
////            syncPhenologyPlusData(deviceId, startTimestamp, endTimestamp);// 同步物候+数据（文档"物候+接口"）
////            syncInsectData(deviceId, startTimestamp, endTimestamp);       // 同步虫情灯数据（文档"虫情灯数据接口"）
////            syncAudioPatternData(deviceId, startTimestamp, endTimestamp); // 同步声纹数据（文档"声纹数据接口"）
//        });
//    }




    /**
     * 每日凌晨2点执行：查询前一天原始数据→解析→计算日均值→存储
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    @Async
    public void calculateYesterdayDailyAvg() {
        // 使用并行流处理设备分组
        List<DeviceGroup> groups = deviceGroupMapper.selectList(new LambdaQueryWrapper<>(DeviceGroup.class).in(DeviceGroup::getId,new String[]{"1","3"}));
        groups.parallelStream().forEach(this::processGroupData);
    }

//    @PostConstruct
//    public void initStatistics() {
//        List<DeviceGroup> groups = deviceGroupMapper.selectList(null);
//        for (DeviceGroup device : groups) {
//            String date = redisTemplate.opsForValue().get(String.format(STATISTICS_DATE_KEY, device.getId()));
//            LocalDate yesterday = LocalDate.now().minusDays(1);
//            if (date == null) {
//                date = START_DATE;
//            }
//            LocalDate statisticsDate = LocalDate.parse(date);
//            while (statisticsDate.isBefore(yesterday)) {
//                long startTs = statisticsDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
//                long endTs = statisticsDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() - 1;
//                processGroupData(device, statisticsDate, startTs, endTs);
//                statisticsDate=statisticsDate.plusDays(1);
//            }
//            redisTemplate.opsForValue().set(String.format(STATISTICS_DATE_KEY, device.getId()), statisticsDate.toString());
//        }
//    }

    /**
     * 处理单个设备分组的原始数据
     */

    private void processGroupData(DeviceGroup group) {
        List<String> deviceIds = List.of(group.getDeviceIds().split(","));
        if (CollectionUtils.isEmpty(deviceIds)) {
            return;
        }

        for (String deviceId : deviceIds) {
            // 获取设备layout（含unit）
            DeviceInfo deviceInfo = deviceInfoMapper.selectOne(
                    new LambdaQueryWrapper<DeviceInfo>().eq(DeviceInfo::getDeviceId, deviceId)
            );
            if (deviceInfo == null || CollectionUtils.isEmpty(deviceInfo.getLayout())) {
                continue;
            }


            // 2. 查询该设备最近一次原始数据
            WeatherData rawData = realTimeDataService.getLatestWeatherData(deviceId).block();
            if (Objects.isNull(rawData)) {
                continue;
            }
            // 3. 保存或更新该条原始数据
            boolean isParse = saveOrUpdateWeatherData(rawData);

            if (!isParse) {
                continue;
            }
            // 4. 解析并存储解析结果
            List<WeatherDataParsed> parsedList = dataParser.parse(
                    rawData.getId(),
                    rawData.getDeviceId(),
                    rawData.getTimestamp(),
                    rawData.getDataArray(),
                    deviceInfo.getLayout()
            );
            if (CollectionUtils.isNotEmpty(parsedList)) {
                parsedList.forEach(this::saveOrUpdateParsedData);
            }
        }
    }


    public boolean saveOrUpdateWeatherData(WeatherData weatherData) {
        // 构造查询条件
        LambdaQueryWrapper<WeatherData> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherData::getDeviceId, weatherData.getDeviceId())
                .eq(WeatherData::getTimestamp, weatherData.getTimestamp());

        // 查询是否存在相同记录
        WeatherData existingData = weatherDataMapper.selectOne(queryWrapper);
        if (!Optional.ofNullable(existingData).isPresent()){
            weatherData.setCreateTime(LocalDateTime.now());
            // 不存在则插入
            weatherDataMapper.insert(weatherData);
            return true;
        }
        return false;
//        if (existingData != null) {
//            // 存在则更新
//            weatherData.setId(existingData.getId());
//            weatherDataMapper.updateById(weatherData);
//        } else {
//            weatherData.setCreateTime(LocalDateTime.now());
//            // 不存在则插入
//            weatherDataMapper.insert(weatherData);
//        }
    }
    public void saveOrUpdateParsedData(WeatherDataParsed  weatherDataParsed) {

        // 构造查询条件
        LambdaQueryWrapper<WeatherDataParsed> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherDataParsed::getDeviceId, weatherDataParsed.getDeviceId())
                .eq(WeatherDataParsed::getTimestamp, weatherDataParsed.getTimestamp())
                .eq(WeatherDataParsed::getSensorName, weatherDataParsed.getSensorName())
                .last("limit 1");

        // 查询是否存在相同记录
        WeatherDataParsed existingData = weatherDataParsedMapper.selectOne(queryWrapper);
        if (!Optional.ofNullable(existingData).isPresent()){
            weatherDataParsed.setParseTime(LocalDateTime.now());
            // 不存在则插入
            weatherDataParsedMapper.insert(weatherDataParsed);
        }

//        if (existingData != null) {
//            // 存在则更新
//            weatherDataParsed.setId(existingData.getId());
//            weatherDataParsedMapper.updateById(weatherDataParsed);
//        } else {
//            weatherDataParsed.setParseTime(LocalDateTime.now());
//            // 不存在则插入
//            weatherDataParsedMapper.insert(weatherDataParsed);
//        }
    }
    /**
     * 同步气象数据（含解析）
     */
    private void syncWeatherData(String deviceId, Long startTs, Long endTs) {
        // 1. 查询设备layout
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(
                new LambdaQueryWrapper<DeviceInfo>().eq(DeviceInfo::getDeviceId, deviceId)
        );
        if (deviceInfo == null || deviceInfo.getLayout() == null) {
            return; // 无layout配置，跳过解析
        }

        // 2. 获取原始数据并处理
        realTimeDataService.getWeatherDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<WeatherData> rawDataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(rawDataList)) {
                        // 3. 存储原始数据
                        rawDataList.forEach(rawData -> {
                            rawData.setCreateTime(LocalDateTime.now());
                            weatherDataMapper.insert(rawData);

                            // 4. 解析并存储解析结果
                            List<WeatherDataParsed> parsedList = dataParser.parse(
                                    rawData.getId(),
                                    rawData.getDeviceId(),
                                    rawData.getTimestamp(),
                                    rawData.getDataArray(), // 直接使用dataArray，无需转换
                                    deviceInfo.getLayout()
                            );
                            if (CollectionUtils.isNotEmpty(parsedList)) {
                               weatherDataParsedMapper.insert(parsedList);
                            }
                        });
                    }
                });
    }



    /**
     * 同步物候数据（对应文档"物候接口"）
     */
    private void syncPhenologyData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getPhenologyDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<PhenologyData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        phenologyDataMapper.insert(dataList);
                    }
                });
    }

    /**
     * 同步盖度数据（对应文档"盖度接口"）
     */
    private void syncCoverageData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getCoverageDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<CoverageData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        coverageDataMapper.insert(dataList);
                    }
                });
    }

    /**
     * 同步盖度+数据（对应文档"盖度+接口"，文档Revision 2.7新增）
     */
    private void syncCoveragePlusData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getCoveragePlusDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<CoveragePlusData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        coveragePlusDataMapper.insert(dataList);
                    }
                });
    }

    /**
     * 同步光谱物候数据（对应文档"光谱物候接口"，文档Revision 2.3新增）
     */
    private void syncSpectrumData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getSpectrumDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<SpectrumData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        spectrumDataMapper.insert(dataList);
                    }
                });
    }

    /**
     * 同步物候+数据（对应文档"物候+接口"，文档Revision 2.5新增）
     */
    private void syncPhenologyPlusData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getPhenologyPlusDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<PhenologyPlusData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        phenologyPlusDataMapper.insert(dataList);
                    }
                });
    }

    /**
     * 同步虫情灯数据（对应文档"虫情灯数据接口"）
     */
    private void syncInsectData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getInsectDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<InsectData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        insectDataMapper.insert(dataList);
                    }
                });
    }

    /**
     * 同步声纹数据（对应文档"声纹数据接口"，文档Revision 2.6新增）
     */
    private void syncAudioPatternData(String deviceId, Long startTs, Long endTs) {
        realTimeDataService.getAudioPatternDataByTimeRange(deviceId, startTs, endTs)
                .subscribe(response -> {
                    List<AudioPatternData> dataList = response.getValue();
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        audioPatternDataMapper.insert(dataList);
                    }
                });
    }
}